package service

import (
	"context"
	"gitee.com/chicken-c/go-learn/webook/internal/domain"
	"gitee.com/chicken-c/go-learn/webook/internal/events/article"
	"gitee.com/chicken-c/go-learn/webook/internal/repostiory"
	"gitee.com/chicken-c/go-learn/webook/pkg/logger"
	"github.com/gin-gonic/gin"
	"time"
)

//go:generate mockgen -destination=./mocks/mock_article.go -package=mocks . ArticleService
type ArticleService interface {
	Save(ctx context.Context, art domain.Article) (int64, error)
	Publish(ctx *gin.Context, art domain.Article) (int64, error)
	WithDraw(ctx *gin.Context, artId int64, authorId int64) error
	List(ctx *gin.Context, offset int64, limit int64, authorId int64) ([]domain.Article, error)
	Detail(ctx *gin.Context, artId int64) (domain.Article, error)
	PubDetail(ctx *gin.Context, artId, uId int64) (domain.Article, error)
	ListPub(ctx context.Context, start time.Time, offset, limit int64) ([]domain.Article, error)
}

type articleService struct {
	repo     repostiory.ArticleRepostiory
	producer article.Producer

	l logger.Logger
}

func (a *articleService) ListPub(ctx context.Context, start time.Time, offset, limit int64) ([]domain.Article, error) {
	arts, err := a.repo.ListPub(ctx, start, offset, limit)
	if err != nil {
		return nil, err
	}

	return arts, nil
}

func NewArticleService(repo repostiory.ArticleRepostiory, producer article.Producer, l logger.Logger) ArticleService {
	return &articleService{
		repo:     repo,
		producer: producer,
		l:        l,
	}
}

func (a *articleService) PubDetail(ctx *gin.Context, artId, uId int64) (domain.Article, error) {
	art, err := a.repo.GetPubByartId(ctx, artId)

	//发送阅读计数消息
	go func() {
		if err == nil {
			er := a.producer.ProducerReadEvent(article.ReadEvent{
				Uid: uId,
				Aid: artId,
			})

			if er != nil {
				a.l.Error("发送阅读计数消息失败", logger.Field{
					Key: "uid",
					Val: uId,
				}, logger.Field{
					Key: "aId",
					Val: artId,
				}, logger.Field{
					Key: "error",
					Val: er,
				})
			}
		}
	}()

	return art, err
}

func (a *articleService) Detail(ctx *gin.Context, artId int64) (domain.Article, error) {
	return a.repo.GetByArticleId(ctx, artId)
}

func (a *articleService) List(ctx *gin.Context, offset int64, limit int64, authorId int64) ([]domain.Article, error) {
	return a.repo.GetByAuthorId(ctx, offset, limit, authorId)
}

func (a *articleService) WithDraw(ctx *gin.Context, artId int64, authorId int64) error {
	return a.repo.SyncStatus(ctx, artId, authorId)
}

func (a *articleService) Publish(ctx *gin.Context, art domain.Article) (int64, error) {
	art.Status = domain.ArticleStatusPublished
	return a.repo.Save(ctx, art)
}

func (a *articleService) Save(ctx context.Context, art domain.Article) (int64, error) {
	art.Status = domain.ArticleStatusUnPublished
	if art.Id > 0 {
		return art.Id, a.repo.Update(ctx, art)
	}
	return a.repo.Create(ctx, art)
}
